package onez.project.core.filter.mock;

import onez.project.common.config.Rule;
import onez.project.common.utils.JSONUtil;
import onez.project.core.context.GatewayContext;
import onez.project.core.filter.Filter;
import onez.project.core.filter.FilterAspect;
import onez.project.core.helper.ResponseHelper;
import onez.project.core.response.GatewayResponse;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

import static onez.project.common.constant.FilterConst.*;

/**
 * MockFilter类
 * 前端mock过滤器，用于在网关处理流程中返回预设的模拟响应数据。
 *
 * 核心功能：
 * 1. 根据路由规则配置的mock数据，拦截匹配的请求
 * 2. 构造并返回预设的HTTP响应
 * 3. 终止后续过滤器链的执行
 *
 * 实现逻辑：
 * - 通过请求方法+路径的组合键匹配mock规则
 * - 支持动态配置的mock响应内容
 * - 自动完成响应写回和请求终止操作
 */
@Slf4j
@FilterAspect(id=MOCK_FILTER_ID,
        name = MOCK_FILTER_NAME,
        order = MOCK_FILTER_ORDER)
public class MockFilter implements Filter {

    /**
     * 执行mock过滤处理
     *
     * @param ctx 网关上下文对象，包含请求/响应信息及路由配置
     * @throws Exception 当JSON解析或响应写回出现异常时抛出
     *
     * 处理流程：
     * 1. 检查当前路由是否配置mock规则
     * 2. 解析请求方法+路径组合键
     * 3. 匹配到mock规则时构造模拟响应
     * 4. 标记请求为已处理并终止后续流程
     */
    @Override
    public void doFilter(GatewayContext ctx) throws Exception {
        // 检查当前路由规则是否配置mock过滤器
        Rule.FilterConfig config = ctx.getRule().getFilterConfig(MOCK_FILTER_ID);
        if (config == null) {
            return;
        }

        // 解析mock配置为键值对映射表，格式：{"GET /api/path": "mock_response"}
        Map<String, String> map = JSONUtil.parse(config.getConfig(), Map.class);

        // 构建请求方法+路径的组合查询键
        String compositeKey = ctx.getRequest().getMethod().name() + " " + ctx.getRequest().getPath();
        String value = map.get(compositeKey);

        // 命中mock规则时的处理流程
        if (value != null) {
            // 构造网关响应对象并标记已处理
            ctx.setResponse(GatewayResponse.buildGatewayResponse(value));
            ctx.written();

            // 将mock响应写回客户端
            ResponseHelper.writeResponse(ctx);

            // 记录mock日志：请求方法 请求路径 mock响应内容
            log.info("mock {} {} {}", ctx.getRequest().getMethod(), ctx.getRequest().getPath(), value);

            // 终止后续过滤器执行
            ctx.terminated();
        }
    }
}
